#pragma once
#include <pthread.h>

template <class T>
class BlockQueue  //其实就是消费者和生产者线程之间可以进行通信的共享资源
{
public:
    BlockQueue(int maxcap)
    :_maxcap(maxcap)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&c_pond, nullptr);
        pthread_cond_init(&p_pond, nullptr);
    }

    void Push(const T& task)
    {
        pthread_mutex_lock(&mutex);
        while(q.size() == _maxcap)//为了防止伪唤醒 当多个线程被从条件变量里唤醒，这些被唤醒的线程竞争到锁后，就会从pthread_cond_wait这段代码执行，因此要进行重新判断，因此要加while循环判断
        {     //生产者生产到_maxcap最大值时，该线程进入条件变量里等待
            pthread_cond_wait(&p_cond, _mutex);//调用该接口时，该线程的锁被释放
        }
        q.push(task);
        pthread_mutex_unlock(&mutex);
        pthread_cond_signal(&c_cond);
    }

    T Pop()
    {
        pthread_mutex_lock(&mutex);
        while(q.size() == 0)
        {
            pthread_cond_wait(&p_cond, _mutex);
        }
        Task task = q.front();
        q.pop();
        pthread_cond_signal(&p_cond);
        pthread_mutex_unlock(&mutex);
        return task;
    }

    ~BlockQueue()
    {
        pthread_mutex_destroy(&mutex);
        pthread_cond_destroy(&c_cond);
        pthread_cond_destroy(&p_cond);
    }

private:
    std::queue<T> q;
    int _maxcap;//消费者和生产者共享资源（队列）中生产者可以生产的最大限量
    pthread_mutex_t _mutex;
    pthread_cond_t c_cond; //消费者的条件变量
    pthread_cond_t p_cond; //生产者的条件变量
};